package com.tian.hello.ui

import android.graphics.drawable.GradientDrawable
import android.os.CountDownTimer
import android.text.Html
import android.util.Log
import android.widget.TextView
import androidx.core.util.Pools
import androidx.lifecycle.MutableLiveData
import androidx.recyclerview.widget.LinearLayoutManager
import com.tian.arch.Foundation
import com.tian.arch.base.BaseActivity
import com.tian.arch.base.BaseViewModel
import com.tian.arch.config.showToast
import com.tian.arch.function.adapter.core.LiteAdapter
import com.tian.arch.function.adapter.core.ViewTypeFinder
import com.tian.arch.function.adapter.diff.DefaultDiffCallback
import com.tian.arch.function.http.Resp
import com.tian.arch.function.http.RetrofitManager
import com.tian.arch.util.*
import com.tian.arch.util.divider.RecycleViewDivider
import com.tian.hello.R
import com.tian.hello.databinding.ActivityArchTestBinding
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import retrofit2.http.Body
import retrofit2.http.POST

data class UserInfo(
    val id: Int,
    val name: String,
    val age: Int
)

interface UserApi {
    @POST(value = "resource-bs-api/client/getUserInfo")
    suspend fun getUsers(): Resp<List<UserInfo>>
}

class UserRepository {
    private val api by lazy { RetrofitManager.obtainApiService(UserApi::class.java) }
    suspend fun getUsers() = api.getUsers()
}

class UserVm : BaseViewModel() {
    private val repo by lazy { UserRepository() }
    val getUserResp = MutableLiveData<List<UserInfo>>()

    fun getUsers() {
        launch(
            { repo.getUsers() },
            {
                getUserResp.value = it.data!!
            },
            showLoading = true
        )
    }
}

class ArchTestAc : BaseActivity<UserVm, ActivityArchTestBinding>(ActivityArchTestBinding::inflate) {

    override val vm: UserVm by lazy { UserVm() }
    private lateinit var testAdapter: LiteAdapter<UserInfo>
    private val testData = mutableListOf(UserInfo(1, "LiLu", 21), UserInfo(2, "王6", 19), UserInfo(3, "李四", 3), UserInfo(4, "张三", 53))

    override fun initPage() {
        initAdapter()
        initTest()
//        vm.getUsers()

//        val duration = 5
//        disposableManager.scope.launch(Dispatchers.IO) {
//            for (i in 0 until duration) {
//                Log.d("ArchTestAc", "current thread = ${Thread.currentThread().name}")
//                delay(1000)
//            }
//            // 定时时间到 切去主线程
//            withContext(Dispatchers.Main) {
//                Log.d("ArchTestAc", "current thread = ${Thread.currentThread().name}")
//            }
//        }
    }

    override fun subscribeLiveData() {
        observe(vm.getUserResp) {
            testAdapter.refreshData(it)
        }
    }

    private fun initAdapter() {
        testAdapter = LiteAdapter.create(this) {
            register(R.layout.item_name, 0) { holder, item, position ->
                holder
                    .doAction<TextView>(R.id.name) {
                        it.text = item.name
                        it.setTextColor(Foundation.context().resources.getColor(R.color.colorAccent))
                    }
            }

            register(R.layout.item_name_and_age, 1) { holder, item, position ->
                holder
                    .doAction<TextView>(R.id.name) {
                        it.text = item.name
                        it.setTextColor(Foundation.context().resources.getColor(R.color.colorAccent))
                    }
                    .setText(R.id.age, item.age.toString())
            }

            registerViewTypeFinder(object : ViewTypeFinder<UserInfo> {
                override fun getViewType(position: Int, item: UserInfo): Int {
                    return item.id % 2
                }
            })

            itemClickListener { index, item -> showToast(item.name + "被点中了") }

            itemLongClickListener { index, item -> showToast(item.name + "被长按了") }

            // 可选配置 ，启用DiffUtil更新
            autoDiff(DefaultDiffCallback())
        }

        vb.myRc.run {
            adapter = testAdapter
            layoutManager = LinearLayoutManager(this@ArchTestAc)
            addItemDecoration(
                RecycleViewDivider(
                    context,
                    LinearLayoutManager.HORIZONTAL,
                    32,
                    this@ArchTestAc.resources.getColor(R.color.colorPrimary)
                )
            )
        }

        testAdapter.refreshData(testData)
    }

    private fun initTest() {

        vb.run {
            // shape 使用
            ringTv.background = createShape(solidColor = R.color.colorAccent.toResColor(this@ArchTestAc), shape = GradientDrawable.OVAL)


            test1.background =
                createShape(solidColor = R.color.colorAccent.toResColor(this@ArchTestAc), cornerRadius = ShapeCornerRadius.Radius8)

            test2.background = createShape(
                solidColor = R.color.colorAccent.toResColor(this@ArchTestAc),
                radii = arrayOf(
                    ShapeCornerRadius.Radius8,
                    ShapeCornerRadius.Radius8,
                    ShapeCornerRadius.Radius16,
                    ShapeCornerRadius.Radius16,
                    ShapeCornerRadius.RadiusNone,
                    ShapeCornerRadius.RadiusNone,
                    ShapeCornerRadius.RadiusNone,
                    ShapeCornerRadius.RadiusNone
                )
            )

            test3.background = createShape(
                solidColor = R.color.colorAccent.toResColor(this@ArchTestAc),
                cornerRadius = ShapeCornerRadius.Radius8,
                strokeWidth = ShapeStokeWidth.Px3,
                strokeColor = R.color.colorAccent
            )

            test4.background = createShape(
                cornerRadius = ShapeCornerRadius.Radius8,
                gradientColors = intArrayOf(
                    R.color.colorAccent.toResColor(this@ArchTestAc),
                    R.color.colorAccent.toResColor(this@ArchTestAc)
                ),
                gradientOrientation = GradientDrawable.Orientation.RIGHT_LEFT
            )

            // selector的使用
            test5.background =
                createSelectorWithColor(
                    R.color.colorPrimary.toResColor(this@ArchTestAc),
                    R.color.colorAccent.toResColor(this@ArchTestAc),
                    SelectorState.Pressed
                )
            test6.setTextColor(
                createTextColorSelector(
                    R.color.white.toResColor(this@ArchTestAc),
                    R.color.colorPrimaryDark.toResColor(this@ArchTestAc),
                    SelectorState.Pressed
                )
            )

            test7.background =
                createSelectorWithIcon(this@ArchTestAc, R.mipmap.ic_launcher_round, R.mipmap.icon_seach, SelectorState.Pressed)

            test8.setTextColor(
                createTextColorSelector(
                    R.color.colorAccent.toResColor(this@ArchTestAc),
                    R.color.cor_b27d3e.toResColor(this@ArchTestAc),
                    SelectorState.Checked
                )
            )
            test8.onClick {
                test8.isChecked = !test8.isChecked
            }

            test10.background = createSelector(
                createShape(
                    solidColor = R.color.white.toResColor(this@ArchTestAc),
                    cornerRadius = ShapeCornerRadius.Radius12,
                    strokeWidth = ShapeStokeWidth.Px3,
                    strokeColor = R.color.cor_b27d3e.toResColor(this@ArchTestAc)
                ),
                createShape(
                    solidColor = R.color.cor_b27d3e.toResColor(this@ArchTestAc),
                    cornerRadius = ShapeCornerRadius.Radius12,
                    strokeWidth = ShapeStokeWidth.Px3,
                    strokeColor = R.color.colorAccent.toResColor(this@ArchTestAc)
                ),
                SelectorState.Checked
            )

            test10.onClick {
                test10.isChecked = !test10.isChecked


                val pool = MyObjPools(3)

                val targetObj = TargetObj()
                targetObj.value = "我是一个测试数据"
                targetObj.actionRelease = {
                    pool.release(it)
                }

                // 先存入数据
                pool.release(targetObj)
                // 再获取数据
                pool.acquire()
            }

            test9.background = createSelector(
                createShape(
                    cornerRadius = ShapeCornerRadius.Radius8,
                    gradientColors = intArrayOf(
                        R.color.colorAccent.toResColor(this@ArchTestAc),
                        R.color.colorAccent.toResColor(this@ArchTestAc)
                    ),
                    gradientOrientation = GradientDrawable.Orientation.RIGHT_LEFT
                ),
                createShape(
                    cornerRadius = ShapeCornerRadius.Radius8,
                    gradientColors = intArrayOf(
                        R.color.colorAccent.toResColor(this@ArchTestAc),
                        R.color.colorAccent.toResColor(this@ArchTestAc)
                    ),
                    gradientOrientation = GradientDrawable.Orientation.LEFT_RIGHT
                ),
                SelectorState.Pressed
            )
        }
    }
}

class TargetObj {

    var value: String = ""
    var actionRelease: ((TargetObj) -> Boolean)? = null

    private val countDownTimer: CountDownTimer
    private val survivalTime = 60 * 1000L// 存活时间为60s
    private val interval = 1000L         // 跳动时间为1s

    init {
        countDownTimer = object : CountDownTimer(survivalTime, interval) {
            override fun onFinish() {
                Log.d("PoolsRelease", "对象=$this, 被释放")
                actionRelease?.invoke(this@TargetObj)
            }

            override fun onTick(millisUntilFinished: Long) {
                Log.d("PoolsRelease", "对象=$this, 存活时间 -1 s")
            }
        }
    }

    fun start() {
        countDownTimer.start()
    }
}


class MyObjPools(maxSize: Int) : Pools.Pool<TargetObj> {
    private var mPool: Array<TargetObj?> = arrayOfNulls<TargetObj?>(maxSize)
    private var mPoolSize: Int = 0

    /**
     * 获取对象方法
     */
    override fun acquire(): TargetObj? {
        if (mPoolSize > 0) {
            val lastPooledIndex = mPoolSize - 1
            val instance = mPool[lastPooledIndex]
            mPool[lastPooledIndex] = null
            mPoolSize--

            instance?.start()
            return instance
        }
        return null
    }

    /**
     * 存入对象方法
     */
    override fun release(instance: TargetObj): Boolean {
        check(!isInPool(instance)) { "Already in the pool!" }
        if (mPoolSize < mPool.size) {
            mPool[mPoolSize] = instance
            mPoolSize++
            return true
        }
        return false
    }

    private fun isInPool(instance: TargetObj): Boolean {
        for (i in 0 until mPoolSize) {
            if (mPool[i] === instance) {
                return true
            }
        }
        return false
    }
}

